/***************************************************************************
 *   Ants - library                                                        *
 *                                                                         *
 *   Copyright (C) 2008 by kuerant                                         *
 *                         <kuerant@gmail.com>                             *
 *                                                                         *
 *   This library is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU Library General Public License as       *
 *   published by the Free Software Foundation; either version 2 of the    *
 *   License, or (at your option) any later version.                       *
 *                                                                         *
 *   This library is distributed in the hope that it will be usefull, but  *
 *   WITHOUT ANY WARRANTY; without even the implied warranty of            *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU      *
 *   Library General Public License for more details.                      *
 *                                                                         *
 *   You should have received a copy of the GNU Library General Public     *
 *   License along with this library; if not, write to the Free Software   *
 *   Foundation, Inc., 59 Temple Place - Suite 330, Boston,                *
 *   MA 02111-1307, USA                                                    *
 ***************************************************************************/

#include    "ants/udpwatcher.hpp"

namespace   ants
{

////////////////////////////////////////////////////////////////////////
//

void    
UdpWatcher::engageSynToSend(const zsocket::Address& address, ant::Packet::serial_type serialFor) throw (ant::Exception)
{
    ant::Packet*    pPacket = NULL;
    getSynPacket(pPacket);
    //pPacket->setSerial();
    pPacket->setSynPacketType();
    pPacket->setSerialFor(serialFor);
    
    room_syn_packet_type::iterator  result_room = m_room_syn_packet_sending.find( address );
    if (m_room_syn_packet_sending.end() == result_room) {
        queue_syn_packet_type       _queue;
        _queue.push_back( pPacket );
        
        m_room_syn_packet_sending[ address ] = _queue;
    }
    else {
        queue_syn_packet_type&  _queue = result_room->second;
        _queue.push_back( pPacket );
    }
}

void    
UdpWatcher::cancelSynToSend(const zsocket::Address& address, ant::Packet::serial_type serialFor) throw (ant::Exception)
{
}
    
////////////////////////////////////////////////////////////////////////
//

void
UdpWatcher::flush(void) throw (ant::Exception)
{
    flushSynPackets();
    
    flushAckPackets();
    
    flushDataPackets();
}

void
UdpWatcher::flushSynPackets(void) throw (ant::Exception)
{
    for (room_syn_packet_type::iterator it_room = m_room_syn_packet_sending.begin();
            it_room != m_room_syn_packet_sending.end();
            ++it_room ) {
        const zsocket::Address&     _address = it_room->first;
        
        queue_syn_packet_type&      _queue = it_room->second;
        
        // send packets 
        for (queue_syn_packet_type::iterator it_queue = _queue.begin();
                it_queue != _queue.end();
                ++it_queue ) {
            ant::Packet*    _pPacket = *it_queue;
            
            try {
                m_pUdper->sendto(_address, _pPacket->getPack(), _pPacket->getPackSize());
            }
            catch (zsocket::Exception& ex) {
                throw ant::Exception(help::String::format("UdpWatcher::%s() zsocket::Exception : [%d] %s", __func__, ex.getCode(), ex.what()), ant::ANTC_EUNKNOWN);
            }
            catch (std::exception& ex) {
                throw ant::Exception(help::String::format("UdpWatcher::%s() std::exception : %s", __func__, ex.what()), ant::ANTC_EUNKNOWN);
            }
        }

        // free packets buffer
        for (queue_syn_packet_type::iterator it_queue = _queue.begin();
                it_queue != _queue.end();
                ++it_queue ) {
            ant::Packet*    _pPacket = *it_queue;
            
            releaseSynPacket(_pPacket);
        }
        
        _queue.clear();
    }
    
    m_room_syn_packet_sending.clear();
}

void
UdpWatcher::flushAckPackets(void) throw (ant::Exception)
{
}

void
UdpWatcher::flushDataPackets(void) throw (ant::Exception)
{
}

void
UdpWatcher::releaseSynPacket(ant::Packet*& pPacket) throw (ant::Exception)
{
    delete pPacket;
    pPacket = NULL;
}

void
UdpWatcher::getSynPacket(ant::Packet*& pPacket) throw (ant::Exception)
{
    pPacket = new ant::Packet(ant::Packet::HEAD_SIZE);
}


////////////////////////////////////////////////////////////////////////
//

    
}   // namespace ants
